package asteroids.model.programs;

import java.util.List;

import asteroids.model.programs.expressions.Expression;
import asteroids.model.programs.expressions.BasicExpressions.BooleanLiteral;
import asteroids.model.programs.expressions.BasicExpressions.DoubleLiteral;
import asteroids.model.programs.expressions.BasicExpressions.Null;
import asteroids.model.programs.expressions.BasicExpressions.Self;
import asteroids.model.programs.expressions.BasicExpressions.Variable;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.Addition;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.And;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.Division;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.Equality;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.GreaterThan;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.GreaterThanOrEqual;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.Inequality;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.LessThan;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.LessThanOrEqual;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.Multiplication;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.Or;
import asteroids.model.programs.expressions.ComposedExpressions.BinaryExpressions.Subtraction;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.Cosine;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.GetDirection;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.GetRadius;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.GetVX;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.GetVY;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.GetX;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.GetY;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.Not;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.Sine;
import asteroids.model.programs.expressions.ComposedExpressions.UnaryExpressions.SquareRoot;
import asteroids.model.programs.statements.Statement;
import asteroids.model.programs.statements.ActionStatements.FireStatement;
import asteroids.model.programs.statements.ActionStatements.SkipStatement;
import asteroids.model.programs.statements.ActionStatements.ThrustOffStatement;
import asteroids.model.programs.statements.ActionStatements.ThrustOnStatement;
import asteroids.model.programs.statements.ActionStatements.TurnStatement;
import asteroids.model.programs.statements.ProgramStatements.AssignStatement;
import asteroids.model.programs.statements.ProgramStatements.ForEachStatement;
import asteroids.model.programs.statements.ProgramStatements.IfStatement;
import asteroids.model.programs.statements.ProgramStatements.PrintStatement;
import asteroids.model.programs.statements.ProgramStatements.SequenceStatement;
import asteroids.model.programs.statements.ProgramStatements.WhileStatement;
import asteroids.model.programs.types.Type;

public class ProgramFactory<E, S, T> implements
		asteroids.model.programs.parsing.ProgramFactory<Expression, Statement, Type> {


	@Override
	public Expression createBooleanLiteral(int line, int column, boolean b) {
		Expression booleanLiteral = new BooleanLiteral(b, line, column);
		return booleanLiteral;
	}
	

	@Override
	public Expression createDoubleLiteral(int line, int column, double d) {
		Expression doubleLiteral = new DoubleLiteral(d, line, column);
		return doubleLiteral;
	}
	
	@Override
	public Expression createVariable(int line, int column, String name) {
		Expression variable = new Variable(name, line, column);
		return variable;
	}
	
	@Override
	public Expression createAdd(int line, int column, Expression e1, Expression e2) {
		Expression add =  new Addition(e1, e2, line, column);
		return add;
	}

	@Override
	public Expression createSubtraction(int line, int column, Expression e1, Expression e2) {
		Expression subtract = new Subtraction(e1, e2, line, column);
		return subtract;
	}
	
	@Override
	public Expression createMul(int line, int column, Expression e1, Expression e2) {
		Expression multiply = new Multiplication(e1, e2, line, column);
		return multiply;
	}
	
	@Override
	public Expression createDivision(int line, int column, Expression e1, Expression e2) {
		Expression divide = new Division(e1, e2, line, column);
		return divide;
	}
	
	@Override
	public Expression createSqrt(int line, int column, Expression e) {
		Expression sqrt = new SquareRoot(e, line, column);
		return sqrt;
	}
	
	@Override
	public Expression createSin(int line, int column, Expression e) {
		Expression sin = new Sine(e, line, column);
		return sin;
	}
	
	@Override
	public Expression createCos(int line, int column, Expression e) {
		Expression cos = new Cosine(e, line, column);
		return cos;
	}

	@Override
	public Expression createAnd(int line, int column, Expression e1, Expression e2) {
		Expression and = new And(e1, e2, line, column);
		return and;
	}
	
	@Override
	public Expression createOr(int line, int column, Expression e1, Expression e2) {
		Expression or = new Or(e1, e2, line, column);
		return or;
	}

	@Override
	public Expression createNot(int line, int column, Expression e) {
		Expression not = new Not(e, line, column);
		return not;
	}
	
	@Override
	public Expression createEquality(int line, int column, Expression e1, Expression e2) {
		Expression equal = new Equality(e1, e2, line, column);
		return equal;
	}
	
	@Override
	public Expression createInequality(int line, int column, Expression e1, Expression e2) {
		Expression inequal = new Inequality(e1, e2, line, column);
		return inequal;
	}
	
	@Override
	public Expression createGreaterThan(int line, int column, Expression e1, Expression e2) {
		Expression greaterThan = new GreaterThan(e1, e2, line, column);
		return greaterThan;
	}

	@Override
	public Expression createGreaterThanOrEqualTo(int line, int column, Expression e1, Expression e2) {
		Expression greaterThanOrEqual = new GreaterThanOrEqual(e1, e2, line, column);
		return greaterThanOrEqual;
	}
	
	@Override
	public Expression createLessThan(int line, int column, Expression e1, Expression e2) {
		Expression lessThan = new LessThan(e1, e2, line, column);
		return lessThan;
	}

	@Override
	public Expression createLessThanOrEqualTo(int line, int column, Expression e1, Expression e2) {
		Expression lessThanOrEqual = new LessThanOrEqual(e1, e2, line, column);
		return lessThanOrEqual;
	}
	
	@Override
	public Expression createGetDirection(int line, int column) {
		Expression self = new Self(line, column);
		Expression getDirection = new GetDirection(self, line, column);
		return getDirection;
	}
	
	@Override
	public Expression createGetRadius(int line, int column, Expression e) {
		Expression getRadius = new GetRadius(e, line, column);
		return getRadius;
	}

	@Override
	public Expression createGetVX(int line, int column, Expression e) {
		Expression getVX = new GetVX(e, line, column);
		return getVX;
	}

	@Override
	public Expression createGetVY(int line, int column, Expression e) {
		Expression getVY = new GetVY(e, line, column);
		return getVY;
	}

	@Override
	public Expression createGetX(int line, int column, Expression e) {
		Expression getX = new GetX(e, line, column);
		return getX;
	}

	@Override
	public Expression createGetY(int line, int column, Expression e) {
		Expression getY = new GetY(e, line, column);
		return getY;
	}
	
	@Override
	public Expression createSelf(int line, int column) {
		Expression self = new Self(line, column);
		return self;
	}
	
	@Override
	public Expression createNull(int line, int column) {
		Expression nullish = new Null(line, column);
		return nullish;
	}
	
	
	
	

	@Override
	public Statement createAssignment(int line, int column, String variable, Expression rhs) {
		Statement assign = new AssignStatement(line, column, variable, rhs);
		return assign;
	}
	
	@Override
	public Statement createForeach(int line, int column,
			asteroids.model.programs.parsing.ProgramFactory.ForeachType type,
			String variableName, Statement body) {
		Statement foreach = new ForEachStatement(line, column, type, variableName, body);
		return foreach;
	}
	
	@Override
	public Statement createWhile(int line, int column, Expression condition, Statement body) {
		Statement whileStatement = new WhileStatement(line, column, condition, body);
		return whileStatement;
	}
	
	@Override
	public Statement createSequence(int line, int column, List<Statement> statements) {
		Statement sequence = new SequenceStatement(line, column, statements);
		return sequence;
	}
	
	@Override
	public Statement createIf(int line, int column, Expression condition, Statement then, Statement otherwise) {
		IfStatement ifStatement = new IfStatement(line, column, condition, then, otherwise);
		return ifStatement;
	}
	
	@Override
	public Statement createEnableThruster(int line, int column) {
		Statement on = new ThrustOnStatement(line, column);
		return on;
	}

	@Override
	public Statement createDisableThruster(int line, int column) {
		Statement off = new ThrustOffStatement(line, column);
		return off;
	}

	@Override
	public Statement createFire(int line, int column) {
		Statement fire = new FireStatement(line, column);
		return fire;
	}
	
	@Override
	public Statement createTurn(int line, int column, Expression angle) {
		Statement turn = new TurnStatement(line, column, angle);
		return turn;
	}
	
	@Override
	public Statement createSkip(int line, int column) {
		Statement skip = new SkipStatement(line, column);
		return skip;
	}
	
	@Override
	public Statement createPrint(int line, int column, Expression e) {
		Statement print = new PrintStatement(line, column, e);
		return print;
	}
	
	
	
	
	@Override
	public Type createBooleanType() {
		return Type.BOOLEAN;
	}

	@Override
	public Type createDoubleType() {
		return Type.DOUBLE;
	}

	@Override
	public Type createEntityType() {
		return Type.ENTITY;
	}
}
